home *** CD-ROM | disk | FTP | other *** search
/ Belgian Amiga Club - ADF Collection / BS1 part 05.zip / BS1 part 5 / LSD.adf / source / BFormat.c.pp / BFormat.c
C/C++ Source or Header  |  1990-09-13  |  20KB  |  870 lines

  1. /*
  2. ** This is a further modification to the Bformat program developed by
  3. ** Bob Bush.  This generation now allows the formatting of any device
  4. ** using either file system.  It still maps out bad sectors, but does it
  5. ** a sector at a time instead of a track at a time.  This is particularly
  6. ** useful for the formatting of hard disks.
  7. **
  8. ** The command format is:
  9. **    BFormat DRIVE <drive> NAME <name> [FFS|NOFFS] [FAST|QUICK|SLOW] [QuIeT]
  10. ** please note that the format is strictly enforced.  All field must be 
  11. ** specified in the specified order.
  12. */
  13.  
  14. /* bformat.c */
  15.  
  16. /*
  17.    When you format a diskette dos grabs 2 blocks for its own use.
  18.    Block 880 is the Root block. Block 881 (normally on a fresh format) is
  19.    the bitmap which in itself indicates the blocks that are available for use
  20.    or currently in use. Generally, a '1' bit means the corresponding block
  21.    is available. A '0' bit means that the block is in use. This sounds
  22.    relatively simple but the AmigaDos implementation needs some 
  23.    explanation.
  24.    
  25.    AmigaDos Block Allocation Map (512 bytes -or- 128 longwords)
  26.    ------------------------------------------------------------
  27.    LongWord   Usage
  28.    --------   -----
  29.       0       location of the block checksum
  30.       1       first bitmap allocation longword, which breaks down as follows:
  31.  
  32.      hi-order bit (31)              lo-order bit (0)
  33.     /                              /
  34.    |                              |
  35.    11111111111111111111111111111111 (32 bit longword)
  36.     \\                           \\\
  37.      \\_block #32                 \\\_block #2
  38.       \_block #33                  \\_block #3
  39.                                     \_block #4
  40.  
  41.  (The above example indicates that blocks 2 thru 33 are available for use)
  42.    
  43.    You might wonder why the bitmap starts at block #2 and not block #0?
  44.    I suppose since the first 2 blocks of every disk are not available for
  45.    file storage, AmigaDos simply chooses to ignore the fact that they exist.
  46.    Another reason could be that if the bitmap included blocks zero and one,
  47.    it might be too easy to figure out.. Hmmmmm..
  48.    Actually I think it corresponds to the well documented (ha) Mountlist
  49.    parameter named 'Reserved' which can be used to segment a hard disk into
  50.    more than one logical drive  If you look at it in that light, the first
  51.    bit in the bitmap corresponds to a block number which is the same as the 
  52.    number of 'Reserved' blocks in the Mountlist file.. Have yet to verify
  53.    this on my hard disk but it sounds logical.  ( Note from Tom Nery - 
  54.    Unfortunately the 2 block offset is not related to the 'Reserved'
  55.    parameter, It was a good guess though).
  56.  
  57.    Inany case, the remainder of the bitmap looks the same e.g. the next
  58.    longword (lo order bit) starts the map for block #34 -- and so on, until
  59.    the map terminates at block #1760...
  60.    
  61.    With the above info, you should be able to figure out how this program
  62.    works.
  63. */
  64.  
  65. /* 
  66.    Date      Programmer  Modification
  67.  =========   ==========  =============================================
  68.  91-Feb-10   T.A.Nery    Removed support for '-C' option but added 
  69.                          support for all mounted disk type devices,
  70.                          including FFS. Also added support for various
  71.                          levels of disk verificaition.
  72.  88-Aug-18   R.W.Bowers  Created this header, added Execute "code" above
  73.  88-Aug-15   R.W.Bowers  Fixed a "minor" BUG!  Using the -C[heck]
  74.                 option "erased" the entire disk!!
  75.  88-Aug-14   R.W.Bowers  Changed reporting from "Track xx" to
  76.                 "Cyl yy, Head z"
  77.  88-Jul-10   R.W.Bowers  Changed # tracks from 160 to "Tracks"
  78.  88-Jul-10   R.W.Bowers  Compiles under Lattice 4.0 or, with -dMANX,
  79.                 under MANX
  80.  88-Mar-28    Bob Bush  cpu-73105,1332 - compiled with Lattice 4.0 
  81. */
  82.  
  83. #include "exec/types.h"
  84. #include "exec/nodes.h"
  85. #include "exec/lists.h"
  86. #include "exec/memory.h"
  87. #include "exec/interrupts.h"
  88. #include "exec/ports.h"
  89. #include "exec/libraries.h"
  90. #include "exec/io.h"
  91. #include "exec/tasks.h"
  92. #include "exec/execbase.h"
  93. #include "exec/devices.h"
  94. #include "devices/trackdisk.h"
  95. #include "intuition/intuition.h"
  96. #include "libraries/dos.h"
  97. #include "libraries/dosextens.h"
  98. #include "libraries/filehandler.h"
  99. #include "stdio.h"
  100. #include <string.h>
  101.  
  102. #define    DONE    0
  103. #define CONT    1
  104.  
  105. #define    FAILURE    0
  106. #define    SUCCESS    1
  107.  
  108. #define    OLD    0x444f5300L
  109. #define    FFS    0x444f5301L
  110.  
  111. #define FAST    1
  112. #define QUICK    2
  113. #define SLOW    3
  114.  
  115. #define    NEXT_DEVICE(device)    ((struct DosList *) BADDR(device->dol_Next))
  116.  
  117. struct    INFO {
  118.     char    Drive[80];    /* Drive Name (eg. df0:)         */
  119.     char    Label[80];    /* Disk Label (eg. Empty)        */
  120.     char    Device[80];     /* Device Name (eg. trackdisk.device)    */
  121.     int    Unit;        /* Device's unit number, per mountlist    */
  122.     long    Sectors;    /* Number of Sectors per track        */
  123.     long    Surfaces;    /* Number of Surfaces             */
  124.     long    LoCyl;        /* Starting Cylinder number        */
  125.     long    HiCyl;        /* Ending Cylinder number        */
  126.     long    FileSystem;    /* File system being used        */
  127.                 /*    0x444f5300 - Old File System    */
  128.                 /*    0x444f5301 - Fast File System    */
  129.     };
  130.  
  131. extern struct DosLibrary *DOSBase;
  132.  
  133. struct    INFO    Info;
  134.  
  135. BOOL formatting = FALSE;
  136.  
  137. ULONG    bitmap_size;    /* Number of bytes allocated to init the bitmaps */
  138. long    *buffer,*bitmap,*track = NULL;
  139. short    abort;
  140. long    TestPattern[4] ={0xFFFFFFFFL, 0xAAAAAAAAL, 0x55555555L, 0x00000000L};
  141. struct    IOStdReq    *mreq  = NULL;
  142. struct    MsgPort        *mport,*dosport = NULL;
  143. struct    StandardPacket    *dpacket;        /* packet for dos */
  144. int    Verify_mode;
  145. int    Quiet;
  146.  
  147.  
  148. /*
  149. ** Convert a BPCL string to a 'C' style string
  150. */
  151. int convert_bstr(out,in,colon)
  152.     BYTE    *in;
  153.     char    *out;
  154.     int     colon;
  155. {
  156.     if ((*in >= 59) || (*in == 0))
  157.         return(FALSE);
  158.  
  159.     memcpy(out, in+1, *in);
  160.     if (colon == TRUE)
  161.     {
  162.         out[*in] = ':';
  163.         out[(*in)+1] = '\0';
  164.     }
  165.     else
  166.         out[*in] = '\0';
  167.  
  168.     return(TRUE);
  169. }
  170.  
  171.  
  172. void write_block(block,buff)
  173.     long    block;
  174.     long    *buff;
  175. {
  176.     mreq->io_Length = 512;
  177.     mreq->io_Data = (APTR)buff;
  178.     mreq->io_Command = CMD_WRITE;
  179.     mreq->io_Offset = block * 512;
  180.     DoIO(mreq);
  181. }
  182.  
  183.  
  184. void Update()
  185. {
  186.     mreq->io_Length = 1;
  187.     mreq->io_Command = CMD_UPDATE;
  188.     DoIO(mreq);
  189. }
  190.  
  191.  
  192. int Clear()
  193. {
  194.     mreq->io_Length = 0;
  195.     mreq->io_Command = CMD_CLEAR;
  196.     DoIO(mreq);
  197.     return(0);
  198. }
  199.  
  200.  
  201. /*
  202. ** Check for the existence of the specified device.  If found, set the 
  203. ** default format parameters for the specific mountlist entry.
  204. */
  205.  
  206. int check_dev(dev,drive)
  207.     struct DeviceNode *dev;
  208.     char           drive[];
  209. {
  210.     struct    FileSysStartupMsg *startup;
  211.     char    Name[80];
  212.     ULONG    *dosenv;
  213.  
  214.  
  215.     if (convert_bstr(Name,BADDR(dev->dn_Name),TRUE) == TRUE)
  216.     {
  217.         if (stricmp(Name,drive) == 0)
  218.         {
  219.             strcpy(Info.Drive,Name);
  220.         }
  221.         else
  222.             return(FAILURE);
  223.     }
  224.     else
  225.         return(FAILURE);
  226.  
  227.     startup = (struct FileSysStartupMsg *)(BADDR(dev->dn_Startup));
  228.     Info.Unit = startup->fssm_Unit;
  229.  
  230.     if (convert_bstr(Name,BADDR(startup->fssm_Device),FALSE) == TRUE)
  231.     {
  232.         strcpy(Info.Device,Name);
  233.     }
  234.  
  235.     dosenv = (ULONG *) (BADDR(startup->fssm_Environ));
  236.  
  237.     Info.Sectors  = dosenv[5];
  238.     Info.Surfaces = dosenv[3];
  239.     Info.LoCyl    = dosenv[9];
  240.     Info.HiCyl    = dosenv[10];
  241.  
  242.     Info.FileSystem = OLD;
  243.     if (dosenv[16] == FFS)
  244.         Info.FileSystem = FFS;
  245.  
  246.     return(SUCCESS);
  247. }
  248.  
  249.  
  250. void cmd_error()
  251. {
  252. printf("\nCommand Format Error.  Command Syntax is:\n");
  253. printf("    BFormat DRIVE <drive> NAME <name> [FFS|NOFFS] [FAST|QUICK|SLOW] [QuIeT]\n");
  254.     exit(10);
  255. }
  256.  
  257.  
  258. int check_struct(dev,drive)
  259.     struct DosList *dev;
  260.     char        drive[];
  261. {
  262.     if ((dev->dol_Type) == DLT_DEVICE)
  263.         if (check_dev(dev,drive) == SUCCESS)
  264.             return(DONE);
  265.     
  266.     return(CONT);
  267. }
  268.     
  269.  
  270. int verify(drive)
  271.     char    drive[];
  272. {
  273.     struct RootNode    *rootNode;
  274.     struct DosInfo    *dosInfo;
  275.     struct DosList    *firstDevice, *device;
  276.  
  277.     rootNode    = (struct RootNode   *) DOSBase->dl_Root;
  278.     dosInfo     = (struct DosInfo    *) BADDR(rootNode->rn_Info);
  279.     firstDevice = (struct DosList *) BADDR(dosInfo->di_DevInfo);
  280.  
  281.     for (device = firstDevice ; device ; device = NEXT_DEVICE(device))
  282.     {
  283.         if (check_struct(device,drive) == DONE)
  284.             return(SUCCESS);
  285.     }
  286.     printf("\nDrive %s Not Found", drive);
  287.     return(FAILURE);
  288. }
  289.     
  290.  
  291. int chk_params(cnt,args)
  292.     int     cnt;
  293.     char    *args[];
  294. {
  295.     int     i;
  296.  
  297. /* Check if the correct number of arguments */
  298.     if (cnt < 5)
  299.         return(FAILURE);
  300.  
  301. /* Make sure all keywords are valid */
  302.     if (stricmp(args[1],"DRIVE"))
  303.         return(FAILURE);
  304.     else if (verify(args[2]) != SUCCESS)
  305.         return(FAILURE);
  306.  
  307.     if (stricmp(args[3],"NAME"))
  308.         return(FAILURE);
  309.     else
  310.         strcpy(Info.Label,args[4]);
  311.  
  312.     Verify_mode = QUICK;
  313.     Quiet       = FALSE;
  314.     for (i = 5 ; i < cnt ; ++i)
  315.     {
  316.         if (stricmp(args[i],"FFS") == 0)
  317.             Info.FileSystem = FFS;
  318.         else if (stricmp(args[i],"NOFFS") == 0)
  319.             Info.FileSystem = OLD;
  320.         else if (stricmp(args[i],"SLOW") == 0)
  321.             Verify_mode = SLOW;
  322.         else if (stricmp(args[i],"QUICK") == 0)
  323.             Verify_mode = QUICK;
  324.         else if (stricmp(args[i],"FAST") == 0)
  325.             Verify_mode = FAST;
  326.         else if (strcmp(args[i],"QuIeT") == 0)
  327.             Quiet = TRUE;
  328.         else
  329.             return(FAILURE);
  330.     }
  331.  
  332.     return(SUCCESS);
  333. }
  334.  
  335.  
  336. void inhibit(t)
  337.     long    t;    /* true or false */
  338. {
  339.     struct MsgPort *handler;
  340.     struct StandardPacket *packet = dpacket ;
  341.  
  342.     handler = (struct MsgPort *)DeviceProc(Info.Drive);
  343.     if (!((handler == NULL) || (dosport == NULL)))
  344.     {    
  345.         packet->sp_Msg.mn_Node.ln_Name = (char *)&(packet->sp_Pkt);
  346.         packet->sp_Pkt.dp_Link = &(packet->sp_Msg);
  347.         packet->sp_Pkt.dp_Port = dosport;
  348.         packet->sp_Pkt.dp_Type = ACTION_INHIBIT;
  349.         packet->sp_Pkt.dp_Arg1 = t;
  350.         PutMsg(handler, packet);
  351.         WaitPort(dosport);
  352.         GetMsg(dosport);
  353.     }
  354. }
  355.  
  356.  
  357. void cleanup(err)
  358.     int    err;
  359. {
  360.     inhibit(FALSE);
  361.     if(mreq)
  362.     {
  363.         CloseDevice(mreq);    
  364.         DeleteStdIO(mreq);
  365.         }
  366.  
  367.     if(mport)
  368.         DeletePort(mport);
  369.     if(dosport)
  370.         DeletePort(dosport);
  371.     if(dpacket)
  372.         FreeMem(dpacket,sizeof(struct StandardPacket));
  373.     if(bitmap)
  374.         FreeMem(bitmap,bitmap_size);
  375.     if(buffer)
  376.         FreeMem(buffer,512);
  377.     if(track)
  378.         FreeMem(track,512 * Info.Sectors);
  379.     exit(0);
  380. }    
  381.  
  382.  
  383. /* handle ctrl-c, ctrl-d aborts */
  384. int brk()
  385. {
  386.     int    c;
  387.     char    buf[20];
  388.  
  389.     if(formatting)
  390.     {
  391.         printf("\n*** Break ***");
  392.         printf("\nDo you really want to abort (y/n)? ");
  393.         gets(buf); c = buf[0];
  394.         if (c == 'y' || c == 'Y')
  395.         {
  396.             printf(
  397.             "\nWarning!  Disk may be unusable.\n\n");
  398.             cleanup(0);  /* Was cleanup(999); */
  399.                }
  400.         else
  401.             abort = 0;
  402.  
  403.                return(0);
  404.          }
  405. }
  406.  
  407.  
  408. void format_track(tnum)
  409.     int    tnum;
  410. {
  411.  
  412.     mreq->io_Length = 512 * Info.Sectors;
  413.     mreq->io_Data = (APTR)track;
  414.     mreq->io_Command = TD_FORMAT;
  415.     mreq->io_Offset = tnum * Info.Sectors * 512;
  416.     DoIO(mreq);
  417. }
  418.  
  419.  
  420. void write_track(tnum)
  421.     int    tnum;
  422. {
  423.     mreq->io_Length = 512 * Info.Sectors;
  424.     mreq->io_Data = (APTR)track;
  425.     mreq->io_Command = CMD_WRITE;
  426.     mreq->io_Offset = tnum * Info.Sectors * 512;
  427.     DoIO(mreq);
  428. }
  429.  
  430.  
  431. void set_fbuff(buff,sectors,value)
  432.     ULONG    buff[];
  433.     int    sectors;
  434.     long    value;
  435. {
  436.     int    j;
  437.  
  438.     for(j = 0; j < (128 * sectors);j++)
  439.         buff[j] = value;
  440. }
  441.  
  442.  
  443. /* verify track with abort on critical tracks */
  444. int verify_track(tnum)
  445.     int    tnum;
  446. {
  447.     int    test;
  448.     int    length;
  449.  
  450.     length = 512 * Info.Sectors;
  451.  
  452.     if (Verify_mode == SLOW)
  453.     {
  454.         for (test = 0 ; test < 4 ; ++test)
  455.         {
  456.             set_fbuff(track,Info.Sectors,TestPattern[test]);
  457.             write_track(tnum);
  458.  
  459.             mreq->io_Length = length;
  460.             mreq->io_Data = (APTR)track;
  461.             mreq->io_Command = CMD_READ;
  462.             mreq->io_Offset = tnum * Info.Sectors * 512;
  463.             DoIO(mreq);
  464.             if ((mreq->io_Error) || (mreq->io_Actual != length))
  465.                     return(0);
  466.         }
  467.     }
  468.     else if (Verify_mode == QUICK)
  469.     {
  470.         mreq->io_Length = length;
  471.         mreq->io_Data = (APTR)track;
  472.         mreq->io_Command = CMD_READ;
  473.         mreq->io_Offset = tnum * Info.Sectors * 512;
  474.         DoIO(mreq);
  475.         if ((mreq->io_Error) || (mreq->io_Actual != length))
  476.                 return(0);
  477.     }
  478.     else
  479.     {
  480.         mreq->io_Length = 512;
  481.         mreq->io_Data = (APTR)track;
  482.         mreq->io_Command = CMD_READ;
  483.         mreq->io_Offset = tnum * Info.Sectors * 512;
  484.         DoIO(mreq);
  485.         if ((mreq->io_Error) || (mreq->io_Actual != 512))
  486.                 return(0);
  487.     }
  488.  
  489.            return(1);
  490. }
  491.  
  492.  
  493. void chk_abort()
  494. {
  495.     if (SetSignal(0L, (ULONG) (SIGBREAKF_CTRL_C)) & (SIGBREAKF_CTRL_C))
  496.         brk();
  497. }
  498.  
  499.  
  500. void validate_required()
  501. {
  502.     int    fstat;
  503.     int    sel_track;
  504.  
  505. /*    chk_abort();    */
  506.  
  507. /*
  508. ** First calculate the starting track number
  509. */
  510.     sel_track = Info.LoCyl * Info.Surfaces;
  511. /*
  512. ** Verify that track 0 is usable.
  513. */
  514.     set_fbuff(track,Info.Sectors,Info.FileSystem);
  515.     format_track(sel_track);
  516. /*    chk_abort();    */
  517.  
  518.     formatting = TRUE;
  519.     if (!(fstat = verify_track(sel_track)))
  520.     {
  521.         printf("\nUnable to format track #0.  ");
  522.         printf("Disk not useable.\n\n");
  523.         cleanup(100);
  524.     }
  525.    
  526. /*
  527. ** Now calculate the Root Block's track number
  528. */
  529.     sel_track += (((Info.HiCyl - Info.LoCyl + 1) * Info.Surfaces)/2);
  530. /*
  531. ** Verify that  root block track is usable.
  532. */
  533.     format_track(sel_track);
  534.     if (!(fstat = verify_track(sel_track)))
  535.     {
  536.         printf("\nUnable to format root block.  ");
  537.         printf("Disk not useable.\n\n");
  538.         cleanup(100);
  539.        }
  540. }
  541.  
  542.  
  543. /* mark block as allocated (in use) */
  544. void clear_bitmap(block)
  545.     long    block;
  546. {
  547.     long    lindex;
  548.  
  549.     if ((block - 2) > -1)
  550.     {
  551.         lindex = (block - 2) / 32;
  552.         bitmap[lindex] = bitmap[lindex] & (~(1 << ((block-2) % 32)));
  553.     }
  554. }
  555.  
  556.  
  557. /* mark block as available for use */
  558. void set_bitmap(block)
  559.     int    block;
  560. {
  561.     int    lindex;
  562.  
  563.     if ((block - 2) > -1)
  564.     {
  565.         lindex = (block - 2) / 32;
  566.         bitmap[lindex] = bitmap[lindex] | (1 << ((block-2) % 32));
  567.     }
  568. }
  569.  
  570.  
  571. /* mark track as available */
  572. int set_track(tnum)
  573.     int    tnum;
  574. {
  575.     int    j;
  576.  
  577.     mreq->io_Command = TD_PROTSTATUS;
  578.     DoIO(mreq);
  579.     if(mreq->io_Actual)
  580.     {
  581.         printf("Disk Write Protected!\n");
  582.         printf("\nWarning!  Disk may be unusable.\n\n");
  583.         cleanup(0);  /* Was cleanup(999); */
  584.         return(0);
  585.     }
  586.  
  587.     for(j = (tnum * Info.Sectors) ; 
  588.             j < (tnum * Info.Sectors + Info.Sectors);j++)
  589.         set_bitmap(j);
  590. }
  591.  
  592.  
  593. /* set volume name into root block (BCPL string) */
  594. void set_name(dest,vname)
  595.     char    *dest,*vname;
  596. {
  597.     *dest = (char)strlen(vname);
  598.     dest++;
  599.     while(*vname)
  600.     {
  601.         *dest = *vname;
  602.         dest++; vname++;
  603.     }
  604. }
  605.  
  606.  
  607. void zblock(wp) /* clear buffer to zeros */
  608.     ULONG    wp[];
  609. {
  610.     int    j;
  611.  
  612.     for(j = 0; j < 128; j++)
  613.         wp[j] = 0;
  614. }
  615.  
  616.  
  617. /* checksum= 2's complement of sum of all words in block */
  618. ULONG check_sum(buff)
  619.     ULONG    buff[];
  620. {
  621.     int    j;
  622.     ULONG    cksum;
  623.  
  624.     cksum = 0;
  625.     for(j = 0; j < 128; j++)
  626.         cksum += buff[j];  /* sum all words in block */
  627.     return(-cksum);
  628. }
  629.  
  630.  
  631. /* build initialized root block */
  632. void init_root(wp,vname,blk)
  633.     ULONG    wp[];
  634.     char    *vname;
  635.     long    blk;
  636. {
  637.     int    i, bit_blks;
  638.     ULONG    temp;
  639.  
  640.     temp = 0;
  641.     bit_blks = bitmap_size/512;
  642.     wp[5] = 0;
  643.  
  644.     zblock(wp);
  645.  
  646.     wp[0]   = 0x02;         /* type */
  647.     wp[3]   = 0x48;         /* hashtable size */
  648.     wp[78]  = 0xffffffff;   /* 'true' bitmap flag */
  649.     for (i = 1 ; i <= bit_blks ; ++i)
  650.         wp[78+i]  = blk + i;
  651.     DateStamp(&wp[105]);    /* datestamp */
  652.     set_name(&wp[108],vname); /* disk name (BCPL) string */
  653.     DateStamp(&wp[121]);    /* datestamp */
  654.     wp[127] = 0x01;         /* secondary type = root */
  655.  
  656.     wp[5] = check_sum(wp); /* create root block checksum */
  657.  
  658. }
  659.  
  660.  
  661. void init_bitmap(wp,root_block)
  662.     ULONG    wp[];
  663.     long    root_block;
  664. {
  665.     int   i, bit_blks;
  666.  
  667.     bit_blks = bitmap_size/512;
  668.  
  669.     clear_bitmap(root_block); /* set root block to allocated  */
  670.  
  671.     for (i = 1; i <= bit_blks ; ++i)
  672.         clear_bitmap(root_block + i);
  673. }
  674.  
  675.  
  676. /*
  677. ** Inhibits dos from trying to access drive while we have control. Also puts
  678. ** up DF0:BUSY message, causes dos to re-read disk info on termination.
  679. */
  680. int Checkstat()
  681. {
  682.     mreq->io_Command = TD_CHANGESTATE;
  683.     DoIO(mreq);
  684.  
  685.     if(mreq->io_Actual)
  686.     {
  687.         printf("No Disk In Drive!\n");
  688.         return(1);
  689.     }
  690.     mreq->io_Command = TD_PROTSTATUS;
  691.     DoIO(mreq);
  692.  
  693.     if (mreq->io_Actual)
  694.     {
  695.         printf("Disk Write Protected!\n");
  696.         return(1);
  697.     }
  698.     return(0);
  699. }
  700.  
  701. void format_it()
  702. {
  703.     int    error,fstat,badcount;
  704.     int    bytes, i, j;
  705.     int    block_cnt, cyl_cnt;
  706.     int    block_start, cyl, head, trk;
  707.     char    c;
  708.     long    *map_p, block_num, track_size;
  709.  
  710.     
  711.     badcount    = 0;
  712.     cyl_cnt     = Info.HiCyl - Info.LoCyl + 1;
  713.     block_cnt   = cyl_cnt * Info.Sectors * Info.Surfaces;
  714.     track_size  = Info.Sectors * 512;
  715.     block_start = Info.LoCyl * Info.Sectors * Info.Surfaces;
  716.  
  717.     if (Quiet != TRUE)
  718.     {
  719.        printf("\nDrive = %s    Name = %s\n",
  720.                             Info.Drive, Info.Label);
  721.  
  722.        printf("Insert Disk to be FORMATTED in drive %s.\n",
  723.                                       Info.Drive);
  724.        printf("Press Return when ready: ");
  725.        c = getchar();
  726.     }
  727.     chkabort();
  728.  
  729.     if(!(mport = (struct MsgPort *)CreatePort("FLOPPY0",0)))
  730.         cleanup(100);
  731.     if(!(dosport = (struct MsgPort *)CreatePort("DOSPORT",0)))
  732.         cleanup(100);
  733.     if(!(mreq = (struct IOStdReq *)CreateStdIO(mport)))
  734.         cleanup(100);
  735.     if(!(dpacket=(struct StandardPacket *) 
  736.         AllocMem(sizeof(struct StandardPacket), MEMF_PUBLIC|MEMF_CLEAR)))
  737.         cleanup(100);           
  738.  
  739.     if(error = OpenDevice(Info.Device,Info.Unit,mreq,0))
  740.         cleanup(1);
  741.  
  742.     inhibit(TRUE);
  743. /*    chk_abort();    */
  744.  
  745. /*
  746. ** Determine how many blocks are required for bitmap, then allocate them
  747. ** Block size calculations based upon 508 byte blocks, since the first
  748. ** four bytes of each block are for checksum.
  749. */
  750.     bytes = block_cnt/8;
  751.     for (bitmap_size = 508 ; bitmap_size < bytes ; bitmap_size += 508) ;
  752.  
  753. /*
  754.     printf("\nBitmap_size = %d Bytes or %d Blocks\n",
  755.                         bitmap_size,bitmap_size/508);
  756. */
  757.  
  758.     bitmap_size = bitmap_size / 508 * 512;
  759.     if(!(bitmap = (long *)AllocMem(bitmap_size, MEMF_CLEAR | MEMF_CHIP)))
  760.         cleanup(8);
  761.     if(!(buffer = (long *)AllocMem(512,MEMF_CLEAR | MEMF_CHIP)))
  762.         cleanup(8);
  763.     if(!(track =  (long *)AllocMem(track_size,MEMF_CLEAR | MEMF_CHIP)))
  764.         cleanup(8);
  765.  
  766.     if (Checkstat())
  767.         cleanup(100);
  768.  
  769. /*    chk_abort();    */
  770.     validate_required();
  771.  
  772.     for (cyl = Info.LoCyl ; cyl <= Info.HiCyl ; ++cyl)
  773.     {
  774.         if (Quiet != TRUE)
  775.             printf("Formatting Cylinder %d \n",cyl);
  776.         for (head = 0 ; head < Info.Surfaces ; ++head)
  777.         {
  778.             trk = cyl * Info.Surfaces + head;
  779.  
  780.             format_track(trk);
  781. /*            chk_abort();    */
  782.         }
  783.  
  784.         if (Quiet != TRUE)
  785.             printf("Verifying  Cylinder %d \n",cyl);
  786.         for (head = 0 ; head < Info.Surfaces ; ++head)
  787.         {
  788.             trk = cyl * Info.Surfaces + head;
  789.  
  790.             if (!(fstat = verify_track(trk)))
  791.             {
  792.                 badcount += Info.Sectors;
  793.             }
  794.             else
  795.             {
  796.                 trk = (cyl - Info.LoCyl)
  797.                         * Info.Surfaces + head;
  798.                 set_track(trk);
  799.             }
  800.  
  801. /*            chk_abort();    */
  802.         }
  803.     }
  804.     if (Quiet != TRUE)
  805.         printf("\n%d Sectors Allocated as Bad\n",badcount);
  806.  
  807. /* init boot/root/bitmap blocks and write to disk.. */
  808.     set_fbuff(buffer,1,Info.FileSystem);
  809.     write_block(block_start, buffer);
  810.     set_fbuff(buffer,1,Info.FileSystem);
  811.     write_block(block_start+1, buffer);
  812.  
  813. /* Root block is middle of device */
  814.     block_num = block_cnt/2 + block_start;
  815.     init_root(buffer,Info.Label,(long)(block_cnt/2));
  816. /* printf("Writing Root Block, #%d\n",block_num);    */
  817.     write_block(block_num, buffer);
  818.  
  819.     init_bitmap(bitmap,block_cnt/2);
  820.     for (i = 1, map_p = (long *)bitmap ;
  821.                      i <= (bitmap_size/512) ; ++i, map_p += 128)
  822.     {
  823. /* calculate checksum for each block and insert */
  824.         for (j = 0 ; j < 127 ; ++j)
  825.             buffer[j + 1] = map_p[j];
  826.  
  827.         buffer[0] = 0;
  828.         buffer[0] = check_sum(buffer);
  829.  
  830. /*        printf("Writing Bitmap Block, #%d\n",block_num+i);    */
  831.         write_block((long)(block_num + i), buffer);
  832.     }
  833.  
  834.     Update();
  835.     Clear();
  836.    
  837.     mreq->io_Length  = 0;
  838.     mreq->io_Command = TD_MOTOR;   /* turn off motor */
  839.     DoIO(mreq);
  840.  
  841.     cleanup(0);
  842. }
  843.  
  844.  
  845. main(cnt,arglist)
  846.     int     cnt;
  847.     char    *arglist[];
  848. {
  849.  
  850.     onbreak(brk);
  851.  
  852.     if (chk_params(cnt,arglist) == FAILURE)
  853.         cmd_error();
  854.     else
  855.     {
  856. /*
  857.                 printf("Drive Name:  %s\n",Info.Drive);
  858.         printf("Volume Name: %s\n",Info.Label);
  859.         printf("Device Name: %s\n",Info.Device);
  860.         printf("Unit:        %d\n",Info.Unit);
  861.         printf("No. Sectors:     %ld\n",Info.Sectors);
  862.         printf("No. Surfaces:    %ld\n",Info.Surfaces);
  863.         printf("LoCyl:           %ld\n",Info.LoCyl);
  864.         printf("HiCyl:           %ld\n",Info.HiCyl);
  865.         printf("FileSystem:    0x%lx\n\n",Info.FileSystem);
  866. */
  867.         format_it();
  868.     }
  869. }
  870.